package com.unnamed.collisions.geometry;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

import org.lwjgl.util.vector.Matrix4f;
import org.lwjgl.util.vector.Vector2f;
import org.lwjgl.util.vector.Vector3f;
import org.lwjgl.util.vector.Vector4f;


public class SharedPoint {
	String name;
	float x,y;
	List<SharedPoint> neighbours;
	
	public SharedPoint(String name,float x, float y){
		this.x=x;this.y=y;this.name=name;
	}
	public SharedPoint(float x, float y){
		this(null,x,y);
	}
	
	public String toString(){
		return "("+x+","+y+")";
	}
	
	public SharedPoint getClosestNeighbour(SharedPoint a){

		float min = 0;
		SharedPoint closest = null;
		System.out.println("Evaluating point "+name);
		for(int c=0;c<neighbours.size();c++){
			if(neighbours.get(c)!=a){
				if(a==null){
					a=new SharedPoint("center",1,0); // Nuevo punto con angulo 0
				}
				
				float angle = angle(this, a, neighbours.get(c));
				//System.out.println(angle);
				if(angle>=min){
					min = angle;
					closest=neighbours.get(c);
					System.out.printf("\t (%s,%s,%s) > %.3f\n",a.name,this.name,neighbours.get(c).name,angle);
				}
			}
		}
		System.out.println("Previous "+a.name+" current "+name+" selects "+closest.name+" with "+min);
		return closest;
	}

	
	public static List<SharedPoint> getHull(SharedPoint initial){
		List<SharedPoint> hull = new ArrayList<SharedPoint>();
		
		SharedPoint prev = initial;
		SharedPoint next = initial.getClosestNeighbour(null);
		hull.add(initial);
		
		while(next!=initial){
			hull.add(next);
			SharedPoint aux = next.getClosestNeighbour(prev);
			prev = next;
			next = aux;
		}
		
		return hull;
	}
	
	
	public static float angle(SharedPoint center, SharedPoint a, SharedPoint b){
		/*
		 * Hay que alinear los ejes para que (center,a) se corresponda con el angulo 0
		 */
		
		float a1 = angle(a.x-center.x,a.y-center.y);
		Matrix4f mtx = new Matrix4f();
		mtx.rotate((float) Math.toRadians(-a1), new Vector3f(0,0,1));
		Vector4f v = Matrix4f.transform(mtx, new Vector4f(b.x-center.x,b.y-center.y,0,1), null);

		return angle(v.x,v.y);
	}

	public static void main(String[] args) {
		SharedPoint[] point = new SharedPoint[12];
		
		point[0] = new SharedPoint("0",1,1);
		point[1] = new SharedPoint("1",1,2);
		point[2] = new SharedPoint("2",1,4);
		point[3] = new SharedPoint("3",1,5);
		point[4] = new SharedPoint("4",2,5);
		point[5] = new SharedPoint("5",5,5);
		point[6] = new SharedPoint("6",5,4);
		point[7] = new SharedPoint("7",2,4);
		point[8] = new SharedPoint("8",2,2);
		point[9] = new SharedPoint("9",5,2);
		point[10] = new SharedPoint("10",5,1);
		point[11] = new SharedPoint("11",2,1);
		
		point[0].neighbours = Arrays.asList(new SharedPoint[]{point[1],point[8],point[11]});
		point[1].neighbours = Arrays.asList(new SharedPoint[]{point[0],point[8],point[7],point[2]});
		point[2].neighbours = Arrays.asList(new SharedPoint[]{point[1],point[7],point[4],point[3]});
		point[3].neighbours = Arrays.asList(new SharedPoint[]{point[2],point[4]});
		point[4].neighbours = Arrays.asList(new SharedPoint[]{point[2],point[7],point[5],point[3]});
		point[5].neighbours = Arrays.asList(new SharedPoint[]{point[4],point[7],point[6]});
		point[6].neighbours = Arrays.asList(new SharedPoint[]{point[5],point[7]});
		point[7].neighbours = Arrays.asList(new SharedPoint[]{point[1],point[2],point[4],point[5],point[6],point[8]});
		point[8].neighbours = Arrays.asList(new SharedPoint[]{point[7],point[1],point[0],point[11],point[9]});
		point[9].neighbours = Arrays.asList(new SharedPoint[]{point[8],point[11],point[10]});
		point[10].neighbours = Arrays.asList(new SharedPoint[]{point[9],point[11]});
		point[11].neighbours = Arrays.asList(new SharedPoint[]{point[10],point[9],point[8],point[0]});
		

		List<SharedPoint> hull = getHull(point[0]);
		for(SharedPoint p:hull){
			System.out.println(p.name);
		}
//
//		System.out.println("------");
//		float a1 = ccw_angle(-1,0);
//		float a2 = ccw_angle(-.9f,-.1f);
//		System.out.println(a2-a1);
//		System.out.println(a1+","+a2+","+(a1-a2));
//		System.out.println("------");
//		System.out.println(ccw_angle(-1,0));
//		System.out.println(ccw_angle(-1,1));
//		System.out.println(ccw_angle(0,1));
//		System.out.println(ccw_angle(1,1));
//		System.out.println(ccw_angle(1,0));
//		System.out.println(ccw_angle(1,-1));
//		System.out.println(ccw_angle(0,-1));
//		System.out.println(ccw_angle(-1,-1));
		
		SharedPoint a = new SharedPoint(10,11);
		SharedPoint b = new SharedPoint(9,10);
		SharedPoint c = new SharedPoint(10,10);
		
		System.out.println(SharedPoint.angle(c, a, b));
		
		System.out.println("-----------------------");
		
		//System.out.println(point[9].getClosestNeighbour(null));
	}
	
	/**
	 * Devuelve el angulo formado por el vector (x,y) con el eje -x
	 * @param x
	 * @param y
	 * @return
	 */
	public static float angle(float x, float y){
		float a = (float) Math.toDegrees(Math.atan(y/x));
		if(x<0) {
			a=a+180;
		}
		
		if(a<0){
			a+=360;
		}
		
		return a;//System.out.printf("%.3f, %.3f, %.3f\n",x,y,a);
	}
	
	public static float ccw_angle(float x, float y){
		float a = 180-angle(x,y);
		if(a<0){
			a+=360;
			
		}
		
		return a;
	}
	
}
